package com.stone.serverless.sdk.utils;


import com.stone.serverless.sdk.function.DPConsumer;
import com.stone.serverless.sdk.function.DPFunction;
import com.stone.serverless.sdk.function.DPThConsumer;
import com.stone.serverless.sdk.function.DPTwConsumer;

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: huyi
 * @Date: 2021/4/20 13:56
 */
public final class LambdaUtil {

    private LambdaUtil() {

    }

    /**
     * SerializedLambda 反序列化缓存
     */
    private static final Map<String, WeakReference<SerializedLambda>> FUNC_CACHE = new ConcurrentHashMap<>();


    /**
     * 获取lambda表达式函数（方法）名称
     *
     * @param <T>  Lambda类型
     * @param func 函数（无参方法）
     * @return 函数名称
     */
    public static <T, P, C> String getMethodName(DPFunction<T, P, C, ?> func) {
        return resolve(func).getImplMethodName();
    }


    /**
     * 解析 lambda 表达式, 该方法只是调用了 SerializedLambda 中的方法，在此基础上加了缓存。
     * 该缓存可能会在任意不定的时间被清除
     *
     * @param func 需要解析的 lambda 对象
     * @return 返回解析后的结果
     */
    public static SerializedLambda resolve(Object func) {
        Class<?> clazz = func.getClass();
        String name = clazz.getName();
        return Optional.ofNullable(FUNC_CACHE.get(name))
                .map(WeakReference::get)
                .orElseGet(() -> {
                    SerializedLambda lambda = SerializedLambda.resolve(func);
                    FUNC_CACHE.put(name, new WeakReference<>(lambda));
                    return lambda;
                });
    }


    public static <T> String getMethodName(DPConsumer<T> func) {
        return resolve(func).getImplMethodName();
    }
    public static <T, P, C> String getMethodName(DPThConsumer<T, P, C> func) {
        return resolve(func).getImplMethodName();
    }
    public static <T, P> String getMethodName(DPTwConsumer<T, P> func) {
        return resolve(func).getImplMethodName();
    }
}
